package com.ipfsemc.ipfsemc.wx;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.DateFormat;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * @author: zzx
 * @date: 2018/10/23 14:24
 * @description: 时间工具类
 */

@Component
public class DateUtil {

    /***************************************************************************************************************/
    /*********************************************    基础方法    ***************************************************/
    /***************************************************************************************************************/

    /**
     * 提供时间格式化时的常用格式
     */
    public final String format1 = "yyyy-MM-dd HH:mm:ss:SSS";
    public final String format2 = "yyyy-MM-dd HH:mm:ss";
    public final String format3 = "yyyy-MM-dd HH:mm";
    public final String format4 = "yyyy-MM-dd HH";
    public final String format5 = "yyyy-MM-dd";
    public final String format6 = "yyyyMMddHHmmssSSS";
    public final String format7 = "yyyyMMddHHmmss";
    public final String format8 = "yyyyMMddHHmm";
    public final String format9 = "yyyyMMddHH";
    public final String format10 = "yyyyMMdd";

    /**
     * 获取当前时间戳
     *
     * @return
     */
    public String getNowDate() {
        return String.valueOf(System.currentTimeMillis());
    }

    /**
     * 时间格式化
     *
     * @param date   时间
     * @param format 格式
     * @return 格式化后的字符串
     */
    public String dateFormat(Date date, final String format) {
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 时间格式化
     *
     * @param date   时间
     * @param format 格式
     * @return 格式化后的字符串
     */
    public Date dateFormatDate(Date date, final String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String s = sdf.format(date);
        return dateFormat(s, format);
    }

    /**
     * 时间格式化(异常返回当前时间)
     *
     * @param date   格式化时间
     * @param format 格式
     * @return 时间
     */
    public Date dateFormat(String date, final String format) {
        try {
            return new SimpleDateFormat(format).parse(date);
        } catch (ParseException e) {
            return new Date();
        }
    }

    /**
     * 时间戳转时间并格式化
     *
     * @param date   时间戳
     * @param format 格式
     * @return
     */
    public String dateFormat(long date, final String format) {
        return new SimpleDateFormat(format).format(new Date(date));
    }

    /**
     * 时间戳转时间
     *
     * @param date 时间戳
     * @return
     */
    public Date dateFormat(long date) {
        return new Date(date);
    }

    /**
     * 时间大小比较
     *
     * @param bigDate   较大的时间
     * @param smallDate 较小的时间
     * @param format    格式：format1、format2、format3、format4、format5
     * @return
     */
    public int compareDate(final Date bigDate, final Date smallDate, final String format) {
        return dateFormat(bigDate, format).compareTo(dateFormat(smallDate, format));
    }

    /**
     * 时间大小比较
     *
     * @param bigDate   较大的时间
     * @param smallDate 较小的时间
     * @param format    格式：format1、format2、format3、format4、format5
     * @return
     */
    public int compareDate(final String bigDate, final String smallDate, final String format) {
        return dateFormat(bigDate, format).compareTo(dateFormat(smallDate, format));
    }

    /**
     * 时间差异比较
     * <p>
     * 1、当格式化之后，按先后顺序依次计算，如果格式为 yyyy-MM-dd HH:mm:ss 在月份上存在差异，则返回月份上的差值
     * <p>
     * 2、此方法只用来比较日期是否存在差异，不可用来直接判断时间差的多少，请根据实际业务使用
     *
     * @param bigDate 较大的时间
     * @param small   较小的时间
     * @param format  格式：format1、format2、format3、format4、format5
     * @return
     */
    public boolean compareToDate(final Date bigDate, final Date small, final String format) {
        return dateFormat(bigDate, format).compareTo(dateFormat(small, format)) == 0;
    }

    /**
     * @param date 指定时间
     * @param i    例如：-1 获取指定时间前一秒的时间、 1 获取指定时间后一秒的时间
     * @return
     */
    public Date addSomeSecond(Date date, int i) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.SECOND, i);
        return cal.getTime();
    }

    /**
     * 获取指定时间几分钟前/后的时间
     *
     * @param date 指定时间
     * @param i    例如：-1 获取指定时间前一分钟的时间、 1 获取指定时间后一分钟的时间
     * @return
     */
    public Date addSomeMinute(Date date, int i) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, i);
        return cal.getTime();
    }

    /**
     * 获取指定时间几小时前/后的时间
     *
     * @param date 指定时间
     * @param i    例如：-1 获取指定时间前一小时的时间、 1 获取指定时间后一小时的时间
     * @return
     */
    public Date addSomeHour(Date date, int i) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, i);
        return cal.getTime();
    }

    /**
     * 获取指定时间几天前/后的时间
     *
     * @param date 指定时间
     * @param i    例如：-1 获取指定时间前一天的时间、 1 获取指定时间后一天的时间
     * @return
     */
    public Date addSomeDay(Date date, int i) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, i);
        return cal.getTime();
    }

    /**
     * 获取指定时间几月前/后的时间
     *
     * @param date 指定时间
     * @param i    例如：-1 获取指定时间前一月的时间、 1 获取指定时间后一月的时间
     * @return
     */
    public Date addSomeMonth(Date date, int i) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, i);
        return cal.getTime();
    }

    /**
     * 获取指定时间几年前/后的时间
     *
     * @param date 指定时间
     * @param i    例如：-1 获取指定时间前一年的时间、 1 获取指定时间后一年的时间
     * @return
     */
    public Date addSomeYear(Date date, int i) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, i);
        return cal.getTime();
    }

    /**
     * 将Instant时间转换成java.util.Date
     *
     * @param instant
     * @return
     */
    public Date from(Instant instant) {
        return new Date().from(instant);
    }

    /**
     * 时间差异计算
     *
     * @param bigDate   较大时间
     * @param smallDate 较小时间
     * @return 较小时间 < 较大时间 --> 返回值 > 0
     */
    public int dayDiff(Date bigDate, Date smallDate) {
        Instant bigInst = Instant.ofEpochMilli(bigDate.getTime());
        Instant smallInst = Instant.ofEpochMilli(smallDate.getTime());
        long l = Duration.between(smallInst, bigInst).toDays();
        return (int) l;
    }

    /**
     * 时间差异计算
     *
     * @param bigInst   较大时间
     * @param smallInst 较小时间
     * @return 较小时间 < 较大时间 --> 返回值 > 0
     */
    public int dayDiff(Instant bigInst, Instant smallInst) {
        long l = Duration.between(smallInst, bigInst).toDays();
        return (int) l;
    }


    /**
     * 时间差异计算
     *
     * @param bigDate   较大时间
     * @param smallDate 较小时间
     * @return 较小时间 < 较大时间 --> 返回值 > 0
     */
    public int hourDiff(Date bigDate, Date smallDate) {
        Instant bigInst = Instant.ofEpochMilli(bigDate.getTime());
        Instant smallInst = Instant.ofEpochMilli(smallDate.getTime());
        long l = Duration.between(smallInst, bigInst).toHours();
        return (int) l;
    }

    /**
     * 时间差异计算
     *
     * @param bigDate   较大时间
     * @param smallDate 较小时间
     * @return 较小时间 < 较大时间 --> 返回值 > 0
     */
    public int minutesDiff(Date bigDate, Date smallDate) {
        Instant bigInst = Instant.ofEpochMilli(bigDate.getTime());
        Instant smallInst = Instant.ofEpochMilli(smallDate.getTime());
        long l = Duration.between(smallInst, bigInst).toMinutes();
        return (int) l;
    }

    /**
     * 时间差异计算
     *
     * @param bigDate   较大时间
     * @param smallDate 较小时间
     * @return 较小时间 < 较大时间 --> 返回值 > 0
     */
    public int secondsDiff(Date bigDate, Date smallDate) {
        Instant bigInst = Instant.ofEpochMilli(bigDate.getTime());
        Instant smallInst = Instant.ofEpochMilli(smallDate.getTime());
        long l = Duration.between(smallInst, bigInst).getSeconds();
        return (int) l;
    }


}
